import Immutable from 'immutable';
import { routerRedux } from 'dva/router';
import {
  // prePay,
  // callRefuelBalancePay,
  queryExceptionPayStation,
  exceptionPay,
  queryPayMode,
  prePay,
  genOrder,
  calMoney,
} from '../services/pay';
import { inWechat, pay as wechatPay } from '../utils/wechat';
import toast from '../utils/toast';
import youyuIcon from '../../assets/images/pay/youyu.png';
import wechatIcon from '../../assets/images/pay/wechat.png';
import alipayIcon from '../../assets/images/pay/alipay.png';
import { delay } from '../utils/func';

const PayModeRecord = Immutable.Record({
  id: null,
  type: null,
  payMode: null,
  name: null,
  selected: false,
  show: false,
  alone: true,
  useCoupon: false,
  useBalance: false,
  useCash: false,
}, 'PayModel');

export class PayMode extends PayModeRecord {
  getPayMode() {
    let payMode;
    switch (this.get('id')) {
      case '1':
        payMode = inWechat() ? 'WECHATPUBLIC' : 'WECHATH5';
        break;
      case '2':
        payMode = 'ALIPAYH5';
        break;
      default:
        break;
    }
    return payMode;
  }

  getIcon() {
    let icon;
    switch (this.get('id')) {
      case '1':
        icon = wechatIcon;
        break;
      case '2':
        icon = alipayIcon;
        break;
      default:
        icon = youyuIcon;
        break;
    }
    return icon;
  }
}

export default {
  namespace: 'pay',
  state: Immutable.fromJS({
    order: null,
    exception: {
      station: null,
      card: null,
      success: false,
      ready: false,
    },
    payMode: {
      balance: new PayMode(),
      cash: [],
      canOnlyCoupon: false,
      showCoupon: false,
    },
    money: null,
  }),

  effects: {
    *calPayMoney({ payload }, { call, put }) {
      const res = yield call(calMoney, payload);
      if (res.success) {
        yield put({
          type: 'updateMoney',
          payload: res.data,
        });
      }
    },
    *genOrder({ payload }, { call, put }) {
      const res = yield call(genOrder, payload);
      if (res.success) {
        yield put({
          type: 'updateOrder',
          payload: res.data,
        });
        yield put(routerRedux.push('/pay/payOrder'));
      }
    },
    *initPay({ payload }, { select, put }) {
      const {
        money,
        modeParams,
      } = payload;
      yield put.resolve({
        type: 'fetchPayMode',
        payload: modeParams,
      });
      yield put.resolve({
        type: 'user/fetchBalance',
      });
      const couponList = yield select(state => state.coupon.get('payCouponList'));
      const balancePay = yield select(state => state.pay.getIn(['payMode', 'balance']));
      if (couponList.filter(coupon => coupon.get('selected')).size === 0) {
        const balance = yield select(state => state.user.getIn(['account', 'balance']));
        const showBalance = balancePay.get('show') && Number(balance) > 0; // 是否展示余额支付
        const balanceEnough = Number(balance) >= Number(money); // 余额是否足够
        const firstCashPay = yield select(state => state.pay.getIn(['payMode', 'cash', 0])); // 找到第一个现金支付方式
        const balanceWithCash = firstCashPay && firstCashPay.get('useBalance'); // 余额支付能否与现金支付混用
        // 是否选择余额支付：展示余额，且余额足够或者余额可以与现金支付混用
        const selectBalance = showBalance && (balanceEnough || balanceWithCash);
        // 是否选择现金支付:
        // 1. 选中余额支付且余额不够，且余额可以与现金混用
        // 2. 未选中余额支付， 切有现金支付方式
        const selectCash = (selectBalance && !balanceEnough && balanceWithCash) ||
          (!selectBalance && !!firstCashPay);
        yield put({
          type: 'autoSelectPayMode',
          payload: {
            showBalance,
            selectBalance,
            selectCash,
          },
        });
      }
    },
    *initData({ payload }, { select, put }) {
      const {
        money,
        modeParams,
        ...rest
      } = payload;
      yield put.resolve({
        type: 'coupon/fetchAndCalPayCoupon',
        payload: rest,
      });
      yield put.resolve({
        type: 'fetchPayMode',
        payload: modeParams,
      });
      yield put.resolve({
        type: 'user/fetchBalance',
      });
      const couponList = yield select(state => state.coupon.get('payCouponList'));
      const balancePay = yield select(state => state.pay.getIn(['payMode', 'balance']));
      if (couponList.filter(coupon => coupon.get('selected')).size === 0) {
        const balance = yield select(state => state.user.getIn(['account', 'balance']));
        const showBalance = balancePay.get('show') && Number(balance) > 0; // 是否展示余额支付
        const balanceEnough = Number(balance) >= Number(money); // 余额是否足够
        const firstCashPay = yield select(state => state.pay.getIn(['payMode', 'cash', 0])); // 找到第一个现金支付方式
        const balanceWithCash = firstCashPay && firstCashPay.get('useBalance'); // 余额支付能否与现金支付混用
        // 是否选择余额支付：展示余额，且余额足够或者余额可以与现金支付混用
        const selectBalance = showBalance && (balanceEnough || balanceWithCash);
        // 是否选择现金支付:
        // 1. 选中余额支付且余额不够，且余额可以与现金混用
        // 2. 未选中余额支付， 切有现金支付方式
        const selectCash = (selectBalance && !balanceEnough && balanceWithCash)
          || (!selectBalance && !!firstCashPay);
        yield put({
          type: 'autoSelectPayMode',
          payload: {
            showBalance,
            selectBalance,
            selectCash,
          },
        });
      }
    },
    *fetchPayMode({ payload }, { call, put }) {
      const res = yield call(queryPayMode, payload);
      if (res.success) {
        yield put({
          type: 'updatePayModeList',
          payload: res.data,
        });
      }
    },
    *exceptionPay({ payload }, { call, put }) {
      const res = yield call(exceptionPay, payload);
      if (res.success) {
        yield put.resolve({
          type: 'doPay',
          payload: {
            payMode: payload.payMode,
            type: 'EXCEPTION',
            payinfo: {
              ...res.data,
              package: res.data.packageValue,
            },
          },
        });
      }
    },
    *fetchExceptionPayStation({ payload }, { call, put }) {
      const res = yield call(queryExceptionPayStation, payload);
      if (res.success) {
        yield put({
          type: 'updateExceptionStation',
          payload: res.data,
        });
      }
    },
    *doPay({ payload }, { call, put }) {
      const {
        type,
        orderNo,
        payMode,
        payinfo,
      } = payload;
      switch (payMode) {
        case 'WECHATPUBLIC':
          try {
            let payParam;
            if ((typeof payinfo === 'string' || payinfo instanceof String)) {
              payParam = JSON.parse(payinfo);
            } else {
              payParam = payinfo;
            }
            yield call(wechatPay, payParam);
            switch (type) {
              case 'EXCEPTION':
                toast('支付成功');
                yield put({
                  type: 'exceptionPaySuccess',
                });
                break;
              case 'REFUEL':
                yield put(routerRedux.push(`/${window.source === 'COMMON' ? 'wap' : 'cq'}/result?orderNo=${orderNo}`));
                break;
              case 'ESCORT_BUY_MENBER':
                yield put(routerRedux.push('/escort/result?type=insurance'));
                break;
              case 'QIJI_REFUEL':
                yield put(routerRedux.push(`/qiji/result?type=order&orderNo=${orderNo}`));
                break;
              default:
                break;
            }
          } catch (error) {
            toast(`支付失败:${JSON.stringify(error)}`);
          }
          break;
        case 'ALIPAYH5':
          window.location.href = payinfo;
          // yield put(routerRedux.replace('/pay/alipay', {
          //   payinfo,
          // }));
          break;
        case 'WECHATH5':
          window.location.href = payinfo;
          // yield put(routerRedux.replace(`../pay/wechatPay?url=${encodeURIComponent(payinfo)}`));
          break;
        default:
          break;
      }
      yield call(delay, 2000);
      yield put({
        type: 'payDone',
      });
    },
    prePay: [function *({ payload }, { call, put }) {
      const {
        type,
        ...rest
      } = payload;
      const res = yield call(prePay, rest);
      if (res.success) {
        yield put({
          type: 'doPay',
          payload: {
            type,
            orderNo: rest.payOrderNo,
            payMode: payload.payMode,
            payinfo: res.data.prepayInfo,
          },
        });
      }
    }, { type: 'throttle', ms: 3000 }], // 最短间隔3秒，防止重复点击
  },

  reducers: {
    updateMoney(state, { payload }) {
      return state.set('money', Immutable.fromJS(payload));
    },
    updateOrder(state, { payload }) {
      return state.set('order', Immutable.fromJS(payload));
    },
    autoSelectPayMode(state, { payload }) {
      const {
        showBalance,
        selectBalance,
        selectCash,
      } = payload;
      let newState = state.setIn(['payMode', 'balance', 'show'], showBalance);
      newState = newState.setIn(['payMode', 'balance', 'selected'], selectBalance);
      if (selectCash) {
        newState = newState.setIn(['payMode', 'cash', 0, 'selected'], true);
      }
      return newState;
    },
    selectPayMode(state, { payload }) {
      const { payMode } = payload;
      let newState = state;
      if (payMode.get('type') === 'balance') {
        newState = newState.setIn(['payMode', 'balance', 'selected'], !payMode.get('selected'));
        let cash = newState.getIn(['payMode', 'cash']);
        cash = cash.map((pm) => {
          if (payMode.get('useCash')) {
            return pm;
          } else {
            return pm.set('selected', false);
          }
        });
        newState = newState.setIn(['payMode', 'cash'], cash);
      } else {
        if (!payMode.get('useBalance')) {
          newState = newState.setIn(['payMode', 'balance', 'selected'], false);
        }
        let cash = newState.getIn(['payMode', 'cash']);
        cash = cash.map((pm) => {
          return pm.set('selected', !payMode.get('selected') && pm.get('id') === payMode.get('id'));
        });
        newState = newState.setIn(['payMode', 'cash'], cash);
      }
      return newState;
    },
    updatePayModeList(state, { payload }) {
      const balance = new PayMode({
        type: 'balance',
        name: '余额支付',
        show: payload.balanceRsp.enable === 1,
        alone: payload.balanceRsp.isAlonePay === 1,
        useBalance: true,
        useCoupon: (payload.balanceRsp.payModeGroupList || []).map(pm => pm.payMode).includes(3),
        useCash: (payload.balanceRsp.payModeGroupList || []).map(pm => pm.payMode).includes(2),
      });
      const cash = payload.cashRsp.payTypes.map((item) => {
        return new PayMode({
          type: 'cash',
          name: item === '2' ? '支付宝支付' : '微信支付',
          show: !(item === '2' && inWechat()),
          alone: true,
          id: item,
          useBalance: (payload.cashRsp.payModeGroupList || []).map(pm => pm.payMode).includes(1),
          useCoupon: (payload.cashRsp.payModeGroupList || []).map(pm => pm.payMode).includes(3),
          useCash: true,
        });
      }).filter(pm => pm.get('show'));
      return state.mergeIn(['payMode'], {
        balance,
        cash,
        canOnlyCoupon: payload.couponRsp.isAlonePay === 1,
        showCoupon: payload.couponRsp.enable === 1,
      });
    },
    updateExceptionStation(state, { payload }) {
      return state.mergeIn(['exception'], {
        ready: true,
        station: payload.gasStationName,
        card: payload.viceCardNo,
      });
    },
    exceptionPaySuccess(state) {
      return state.setIn(['exception', 'success'], true);
    },
    clearExceptionPay(state) {
      return state.setIn(['exception', 'success'], false);
    },
  },
};
